package model

import (
	"gitee.com/sansaniot/ssiot-core/logger"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type Model struct {
	Orm      *gorm.DB       `gorm:"-" json:"-"`
	Log      *logger.Helper `gorm:"-" json:"-"`
	Error    error          `gorm:"-" json:"-"`
	Language string         `gorm:"-" json:"-"`
}

func (e Model) Add(model interface{}) (err error) {
	return e.Orm.Model(model).Create(model).Error
}

func (e Model) Mod(model interface{}) (err error) {
	return e.Orm.Model(model).Updates(model).Error
}

func (e Model) ModByConds(model interface{}, conds string, params ...interface{}) (err error) {
	return e.Orm.Model(model).Where(conds, params...).Updates(model).Error
}

func (e Model) ModMap(data interface{}, updates map[string]interface{}, condition ...func(db *gorm.DB) *gorm.DB) error {
	return e.Orm.Model(data).
		Scopes(condition...).
		Updates(updates).
		Error
}

func (e Model) FindOne(model interface{}, condition ...func(db *gorm.DB) *gorm.DB) (err error) {
	err = e.Orm.Model(model).
		Scopes(
			condition...,
		).First(model).Error
	return err
}

func (e Model) FindOneByConds(model interface{}, conds string, params ...interface{}) (err error) {
	return e.Orm.Model(model).Where(conds, params...).First(model).Error
}

func (e Model) FindList(list interface{}, condition ...func(db *gorm.DB) *gorm.DB) (err error) {
	return e.Orm.Model(list).Scopes(
		condition...,
	).Find(list).Limit(-1).Offset(-1).Error
}

func (e Model) FindPage(list interface{}, count *int64, condition ...func(db *gorm.DB) *gorm.DB) (err error) {
	return e.Orm.Model(list).Scopes(
		condition...,
	).Find(list).Limit(-1).Offset(-1).Count(count).Error
}

func (e Model) Del(model interface{}, conds string, params ...interface{}) (err error) {
	return e.Orm.Model(model).Where(conds, params...).Delete(model).Error
}
func (e Model) DeleteByConds(model interface{}, params ...interface{}) error {
	return e.Orm.Model(model).
		Delete(model, params...).
		Error
}

func (e Model) Delete(model interface{}, condition ...func(db *gorm.DB) *gorm.DB) error {
	return e.Orm.Model(model).Scopes(condition...).
		Delete(model).
		Error
}

func (e Model) FindCountByConds(list interface{}, count *int64, conds string, params ...interface{}) error {
	return e.Orm.Model(list).Where(conds, params...).Find(list).Count(count).Error
}

func (e Model) FindCount(model interface{}, count *int64, condition ...func(db *gorm.DB) *gorm.DB) (err error) {
	return e.Orm.Model(model).Scopes(
		condition...,
	).Find(model).Count(count).Error
}

func (e Model) FindListByConds(model interface{}, conds string, params ...interface{}) (err error) {
	return e.Orm.Model(model).Where(conds, params...).Find(model).Error
}

func (e Model) Upsert(data interface{}, conflictColumns ...string) error {
	// 默认id主键字段冲突
	var columns = []string{"id"}
	if len(conflictColumns) > 0 {
		columns = conflictColumns
	}
	clauseColumns := make([]clause.Column, 0)
	for _, v := range columns {
		column := clause.Column{Name: v}
		clauseColumns = append(clauseColumns, column)
	}
	return e.Orm.Model(data).
		Clauses(clause.OnConflict{
			//Columns:   []clause.Column{{Name: "id"}},
			Columns:   clauseColumns,
			UpdateAll: true, // 更新除主键的所有字段
		}).
		Create(data).
		Error
}

func (e Model) UpsertDoUpdate(data interface{}, conflictColumns []string, doUpdates []string) error {
	// 默认id主键字段冲突
	var columns = []string{"id"}
	if len(conflictColumns) > 0 {
		columns = conflictColumns
	}
	clauseColumns := make([]clause.Column, 0)
	for _, v := range columns {
		column := clause.Column{Name: v}
		clauseColumns = append(clauseColumns, column)
	}
	conflict := clause.OnConflict{
		Columns: clauseColumns,
	}
	if len(doUpdates) == 0 {
		conflict.UpdateAll = true
	} else {
		// 更新指定列为新值
		conflict.DoUpdates = clause.AssignmentColumns(doUpdates)
	}
	return e.Orm.Model(data).
		Clauses(conflict).
		Create(data).
		Error
}
